package adapter

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/mars/internal/admin/core/application/client"
	"github.com/mars/internal/admin/core/application/service"
	"github.com/mars/internal/admin/core/domain"
	"github.com/mars/internal/pkg/gins"
	"github.com/mars/pkg/errors"
)

type BookingController struct {
	srv       service.Service
	validator *domain.BookingValidator
}

func NewBookingController(fc domain.Factory) *BookingController {
	return &BookingController{
		srv:       service.NewService(fc),
		validator: domain.NewBookingValidator(),
	}
}

// GetBookingList 获取预约列表
// @Summary 获取预约列表
// @Description 分页查询所有预约信息，支持多种筛选条件
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Param openid query string false "用户openid"
// @Param venueType query string false "场地类型" Enums(family_fishing,lure_fishing,forest_yoga)
// @Param status query string false "预约状态" Enums(pending,confirmed,cancelled,rejected,completed)
// @Param bookingDate query string false "预约日期 (YYYY-MM-DD)"
// @Param timeSlot query string false "时间段" Enums(morning,afternoon,full_day)
// @Param sort query string false "排序字段" default(createTime)
// @Param order query string false "排序方向" Enums(asc,desc) default(desc)
// @Success 200 {object} map[string]interface{} "{"data": [预约列表], "total": 总数}"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/list [get]
func (bc *BookingController) GetBookingList(cxt *gin.Context) (interface{}, int64, error) {
	// 使用domain层验证器验证查询参数
	params, err := bc.validator.ValidateQueryParams(cxt)
	if err != nil {
		return nil, 0, err
	}

	bookings, total, err := bc.srv.BookingSrv().GetBookingList(cxt, params)
	if err != nil {
		return nil, 0, err
	}

	// 转换为view层结构体，包含格式化的时间字符串
	bookingViews := client.ToBookingViewList(bookings)
	return bookingViews, total, nil
}

// GetBookingDetail 获取预约详情
// @Summary 获取预约详情
// @Description 根据预约ID查询预约详细信息
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param bookingId path string true "预约ID"
// @Success 200 {object} domain.Booking "预约详细信息"
// @Failure 400 {object} map[string]interface{} "预约ID参数缺失"
// @Failure 404 {object} map[string]interface{} "预约不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/detail/{bookingId} [get]
func (bc *BookingController) GetBookingDetail(cxt *gin.Context) (interface{}, error) {
	// 使用domain层验证器验证预约ID
	bookingID, err := bc.validator.ValidateBookingID(cxt, "bookingId")
	if err != nil {
		return nil, err
	}

	booking, err := bc.srv.BookingSrv().GetBookingDetail(cxt, bookingID)
	if err != nil {
		return nil, err
	}

	// 转换为view层结构体
	bookingView := client.ToBookingView(booking)
	return bookingView, nil
}

// ConfirmBooking 确认预约
// @Summary 确认预约
// @Description 管理员确认用户的预约申请
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param bookingId path string true "预约ID"
// @Success 200 {object} map[string]interface{} "{"message": "预约确认成功"}"
// @Failure 400 {object} map[string]interface{} "预约ID参数缺失或预约状态不允许确认"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "预约不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/confirm/{bookingId} [put]
func (bc *BookingController) ConfirmBooking(cxt *gin.Context) (*gins.Response, error) {
	// 使用domain层验证器验证预约ID
	bookingID, err := bc.validator.ValidateBookingID(cxt, "bookingId")
	if err != nil {
		return nil, err
	}

	err = bc.srv.BookingSrv().ConfirmBooking(cxt, bookingID)
	if err != nil {
		return nil, err
	}
	return gins.NewSuccessResponse("预约确认成功"), nil
}

// RejectBooking 拒绝预约
// @Summary 拒绝预约
// @Description 管理员拒绝用户的预约申请，需要提供拒绝原因
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param bookingId path string true "预约ID"
// @Param request body map[string]string true "拒绝原因 {\"reason\": \"拒绝原因\"}"
// @Success 200 {object} map[string]interface{} "{"message": "预约拒绝成功"}"
// @Failure 400 {object} map[string]interface{} "预约ID参数缺失或拒绝原因为空"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "预约不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/reject/{bookingId} [put]
func (bc *BookingController) RejectBooking(cxt *gin.Context) (*gins.Response, error) {
	// 使用domain层验证器验证预约ID
	bookingID, err := bc.validator.ValidateBookingID(cxt, "bookingId")
	if err != nil {
		return nil, err
	}

	// 解析请求体
	var request struct {
		Reason string `json:"reason"`
	}
	if err := cxt.ShouldBindJSON(&request); err != nil {
		return nil, errors.New(http.StatusBadRequest, "invalid JSON format: "+err.Error())
	}

	// 使用domain层验证器验证拒绝原因
	if err := bc.validator.ValidateReason(request.Reason); err != nil {
		return nil, err
	}

	err = bc.srv.BookingSrv().RejectBooking(cxt, bookingID, request.Reason)
	if err != nil {
		return nil, err
	}

	return gins.NewSuccessResponse("预约拒绝成功"), nil
}

// CancelBooking 取消预约
// @Summary 取消预约
// @Description 管理员代替用户取消预约，需要提供取消原因
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param bookingId path string true "预约ID"
// @Param request body map[string]string true "取消原因 {\"reason\": \"取消原因\"}"
// @Success 200 {object} map[string]interface{} "{"message": "预约取消成功"}"
// @Failure 400 {object} map[string]interface{} "预约ID参数缺失或取消原因为空"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "预约不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/cancel/{bookingId} [put]
func (bc *BookingController) CancelBooking(cxt *gin.Context) (*gins.Response, error) {
	// 使用domain层验证器验证预约ID
	bookingID, err := bc.validator.ValidateBookingID(cxt, "bookingId")
	if err != nil {
		return nil, err
	}

	// 解析请求体
	var request struct {
		Reason string `json:"reason"`
	}
	if err := cxt.ShouldBindJSON(&request); err != nil {
		return nil, errors.New(http.StatusBadRequest, "invalid JSON format: "+err.Error())
	}

	// 使用domain层验证器验证取消原因
	if err := bc.validator.ValidateReason(request.Reason); err != nil {
		return nil, err
	}

	err = bc.srv.BookingSrv().CancelBooking(cxt, bookingID, request.Reason)
	if err != nil {
		return nil, err
	}

	return gins.NewSuccessResponse("预约取消成功"), nil
}

// CompleteBooking 完成预约
// @Summary 完成预约
// @Description 管理员将已确认的预约标记为完成状态
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param bookingId path string true "预约ID"
// @Success 200 {object} map[string]interface{} "{"message": "预约完成成功"}"
// @Failure 400 {object} map[string]interface{} "预约ID参数缺失或预约状态不允许完成"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 404 {object} map[string]interface{} "预约不存在"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/complete/{bookingId} [put]
func (bc *BookingController) CompleteBooking(cxt *gin.Context) (*gins.Response, error) {
	// 使用domain层验证器验证预约ID
	bookingID, err := bc.validator.ValidateBookingID(cxt, "bookingId")
	if err != nil {
		return nil, err
	}

	err = bc.srv.BookingSrv().CompleteBooking(cxt, bookingID)
	if err != nil {
		return nil, err
	}

	return gins.NewSuccessResponse("预约完成成功"), nil
}

// GetBookingStats 获取预约统计信息
// @Summary 获取预约统计信息
// @Description 获取预约数量的多维度统计信息，包括总数、各状态统计、各场地类型统计
// @Tags 预约管理
// @Accept json
// @Produce json
// @Success 200 {object} domain.BookingStats "统计信息"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/stats [get]
func (bc *BookingController) GetBookingStats(cxt *gin.Context) (interface{}, error) {
	stats, err := bc.srv.BookingSrv().GetBookingStats(cxt)
	if err != nil {
		return nil, err
	}

	return stats, nil
}

// GetAvailableTimeSlots 获取场地可用时间段
// @Summary 获取场地可用时间段
// @Description 查询指定场地在指定日期的可用时间段和剩余容量
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param venueType query string true "场地类型" Enums(family_fishing,lure_fishing,forest_yoga)
// @Param bookingDate query string true "预约日期 (YYYY-MM-DD)"
// @Success 200 {object} domain.AvailableSlots "可用时间段信息"
// @Failure 400 {object} map[string]interface{} "参数错误"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/available-slots [get]
func (bc *BookingController) GetAvailableTimeSlots(cxt *gin.Context) (interface{}, error) {
	// 使用domain层验证器验证可用时间段查询参数
	venueType, bookingDate, err := bc.validator.ValidateAvailableSlotParams(cxt)
	if err != nil {
		return nil, err
	}

	availableSlots, err := bc.srv.BookingSrv().GetAvailableTimeSlots(cxt, venueType, bookingDate)
	if err != nil {
		return nil, err
	}

	return availableSlots, nil
}

// BatchUpdateBookingStatus 批量更新预约状态
// @Summary 批量更新预约状态
// @Description 批量确认或拒绝多个预约
// @Tags 预约管理
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "批量更新请求 {\"bookingIds\": [\"id1\", \"id2\"], \"action\": \"confirm|reject\", \"reason\": \"原因\"}"
// @Success 200 {object} map[string]interface{} "{"message": "批量操作成功", "successCount": 成功数量, "failedCount": 失败数量}"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Failure 401 {object} map[string]interface{} "未授权"
// @Failure 403 {object} map[string]interface{} "权限不足"
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
// @Router /api/v1/admin/booking/batch-update [put]
func (bc *BookingController) BatchUpdateBookingStatus(cxt *gin.Context) (interface{}, error) {
	var request struct {
		BookingIds []string `json:"bookingIds"`
		Action     string   `json:"action"`
		Reason     string   `json:"reason,omitempty"`
	}

	if err := cxt.ShouldBindJSON(&request); err != nil {
		return nil, errors.New(http.StatusBadRequest, "invalid JSON format: "+err.Error())
	}

	// 验证批量更新参数
	if len(request.BookingIds) == 0 {
		return nil, errors.New(http.StatusBadRequest, "booking IDs are required")
	}

	if len(request.BookingIds) > 100 {
		return nil, errors.New(http.StatusBadRequest, "too many booking IDs, maximum 100 allowed")
	}

	if request.Action != "confirm" && request.Action != "reject" {
		return nil, errors.New(http.StatusBadRequest, "action must be 'confirm' or 'reject'")
	}

	if request.Action == "reject" {
		if err := bc.validator.ValidateReason(request.Reason); err != nil {
			return nil, err
		}
	}

	// 执行批量操作
	successCount := 0
	failedCount := 0

	for _, bookingID := range request.BookingIds {
		var err error
		if request.Action == "confirm" {
			err = bc.srv.BookingSrv().ConfirmBooking(cxt, bookingID)
		} else {
			err = bc.srv.BookingSrv().RejectBooking(cxt, bookingID, request.Reason)
		}

		if err != nil {
			failedCount++
		} else {
			successCount++
		}
	}

	return gin.H{
		"message":      "批量操作完成",
		"successCount": successCount,
		"failedCount":  failedCount,
	}, nil
}
